<!-- Mermaid 图表组件 -->
<script setup lang="ts">
import { DocumentCopy, Download, FullScreen, WarningFilled, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import mermaid from 'mermaid';
import svgPanZoom from 'svg-pan-zoom';
import { computed, nextTick, onMounted, onUnmounted, ref, toRefs, watch } from 'vue';

interface Props {
  content: string;
  key?: string | number;
}

const props = withDefaults(defineProps<Props>(), {
  key: '',
});

// 生成唯一的元素ID
const elementId = computed(() => `mermaid-${props.key || Math.random().toString(36).substring(2, 11)}`);

// DOM 引用
const mermaidContainerRef = ref<HTMLElement>();
const codeContainerRef = ref<HTMLElement>();
const errorContainerRef = ref<HTMLElement>();

// 显示状态
const displayState = ref<'chart' | 'code'>('chart');

// 错误状态
const renderError = ref(false);

// 缩放状态
const currentScale = ref(1);

// svg-pan-zoom 实例
let panZoomInstance: any = null;

// 初始化 Mermaid
onMounted(() => {
  // 只初始化一次
  if (!(mermaid as any).isInitialized) {
    mermaid.initialize({
      startOnLoad: false,
      theme: 'default',
    });
    (mermaid as any).isInitialized = true;
  }

  // 渲染图表
  nextTick(() => {
    renderDiagram();
  });
});

// 渲染 Mermaid 图表
async function renderDiagram() {
  if (!mermaidContainerRef.value || !props.content.trim())
    return;

  // 重置错误状态
  renderError.value = false;
  // 生成唯一的图表ID
  const graphId = `graph-${elementId.value}`;

  try {
    mermaidContainerRef.value.innerHTML = '';
    // 使用 Mermaid 渲染
    const { svg } = await mermaid.render(graphId, props.content);

    // 插入 SVG
    mermaidContainerRef.value.innerHTML = svg;

    // 确保错误容器被隐藏，图表容器显示
    if (errorContainerRef.value) {
      errorContainerRef.value.style.display = 'none';
    }
    mermaidContainerRef.value.style.display = 'flex';

    // 等待 DOM 更新后初始化 svg-pan-zoom
    nextTick(() => {
      initializePanZoom();
    });
  }
  catch (error) {
    console.error('Mermaid 渲染错误:', error);
    // 设置错误状态
    renderError.value = true;
    // 删除元素
    document.getElementById(graphId)?.remove();

    // 显示错误容器，隐藏图表容器
    if (mermaidContainerRef.value && errorContainerRef.value) {
      mermaidContainerRef.value.style.display = 'none';
      errorContainerRef.value.style.display = 'flex';
    }
  }
}

// 初始化 svg-pan-zoom
function initializePanZoom() {
  if (!mermaidContainerRef.value)
    return;

  const svgElement = mermaidContainerRef.value.querySelector('svg');
  if (!svgElement)
    return;

  // 强制设置 SVG 高度为 400px
  svgElement.style.height = '400px';
  svgElement.style.width = '100%';
  svgElement.style.maxWidth = '100%';

  // 销毁之前的实例
  if (panZoomInstance) {
    panZoomInstance.destroy();
  }

  // 创建新的 svg-pan-zoom 实例
  panZoomInstance = svgPanZoom(svgElement, {
    zoomEnabled: true,
    controlIconsEnabled: false,
    fit: true,
    center: true,
    minZoom: 0.5,
    maxZoom: 5,
    zoomScaleSensitivity: 0.3,
    panEnabled: true,
    dblClickZoomEnabled: true,
    mouseWheelZoomEnabled: true,
    preventMouseEventsDefault: true,
  });

  // 监听缩放事件
  panZoomInstance.setOnZoom((zoomScale: number) => {
    currentScale.value = zoomScale;
  });
}

// 切换显示模式
function toggleDisplay(type: 'chart' | 'code') {
  displayState.value = type;

  if (!mermaidContainerRef.value || !codeContainerRef.value || !errorContainerRef.value)
    return;

  if (type === 'code') {
    // 显示代码，隐藏图表和错误容器
    codeContainerRef.value.style.display = 'block';
    mermaidContainerRef.value.style.display = 'none';
    errorContainerRef.value.style.display = 'none';
  }
  else {
    // 显示图表或错误容器，隐藏代码
    codeContainerRef.value.style.display = 'none';
    if (renderError.value) {
      // 如果有错误，显示错误容器，隐藏图表容器
      mermaidContainerRef.value.style.display = 'none';
      errorContainerRef.value.style.display = 'flex';
    }
    else {
      // 没有错误，显示图表容器
      mermaidContainerRef.value.style.display = 'flex';
      errorContainerRef.value.style.display = 'none';
    }
  }
}

// 放大
function zoomIn() {
  if (panZoomInstance) {
    panZoomInstance.zoomIn();
  }
}

// 缩小
function zoomOut() {
  if (panZoomInstance) {
    panZoomInstance.zoomOut();
  }
}

// 全屏切换
function toggleFullscreen() {
  const wrapper = document.getElementById(`mermaid-wrapper-${elementId.value}`);
  if (!wrapper)
    return;

  const svgElement = mermaidContainerRef.value?.querySelector('svg');

  if (wrapper.classList.contains('fullscreen')) {
    // 退出全屏
    wrapper.classList.remove('fullscreen');
    document.body.style.overflow = '';
    ElMessage.success('已退出全屏');

    // 恢复 SVG 高度为 400px
    if (svgElement) {
      svgElement.style.height = '400px';
      svgElement.style.minHeight = '400px';
    }
  }
  else {
    // 进入全屏
    wrapper.classList.add('fullscreen');
    document.body.style.overflow = 'hidden';
    ElMessage.success('已进入全屏');

    // 设置 SVG 高度为 100%
    if (svgElement) {
      svgElement.style.height = '100%';
      svgElement.style.minHeight = '100%';
    }
  }
}

// 下载处理
async function handleDownload(command: string) {
  if (command === 'png') {
    await downloadAsPNG();
  }
  else if (command === 'svg') {
    await downloadAsSVG();
  }
}

// 下载为 PNG
async function downloadAsPNG() {
  if (!mermaidContainerRef.value)
    return;

  const svg = mermaidContainerRef.value.querySelector('svg');
  if (!svg)
    return;

  try {
    // 克隆 SVG
    const svgClone = svg.cloneNode(true) as SVGElement;

    // 重置变换和样式
    svgClone.style.transform = 'scale(1)';
    svgClone.style.position = 'static';
    svgClone.style.display = 'block';

    // 获取 SVG 的实际尺寸
    const bbox = svg.getBBox();
    const originalWidth = bbox.width || 6000;
    const originalHeight = bbox.height || 5000;

    // 计算缩放比例，限制最大尺寸
    const maxWidth = 6000;
    const maxHeight = 5000;
    let scale = 1;

    if (originalWidth > maxWidth) {
      scale = maxWidth / originalWidth;
    }
    if (originalHeight * scale > maxHeight) {
      scale = maxHeight / originalHeight;
    }

    const finalWidth = Math.round(originalWidth * scale);
    const finalHeight = Math.round(originalHeight * scale);

    // 设置 SVG 属性
    svgClone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
    svgClone.setAttribute('width', finalWidth.toString());
    svgClone.setAttribute('height', finalHeight.toString());
    svgClone.setAttribute('viewBox', `${bbox.x} ${bbox.y} ${originalWidth} ${originalHeight}`);

    // 确保所有文本元素可见
    const textElements = svgClone.querySelectorAll('text');
    textElements.forEach((text) => {
      text.setAttribute('fill', text.getAttribute('fill') || '#000');
      text.setAttribute('stroke', 'none');
    });

    // 转换为字符串
    const svgString = new XMLSerializer().serializeToString(svgClone);

    // 创建 Canvas
    const canvas = document.createElement('canvas');
    canvas.width = finalWidth;
    canvas.height = finalHeight;
    const ctx = canvas.getContext('2d');

    if (ctx) {
      // 设置白色背景
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, finalWidth, finalHeight);

      // 转换为 Data URL
      const svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`;

      // 创建图片对象
      const img = new Image();

      img.onload = () => {
        // 绘制 SVG 到 Canvas
        ctx.drawImage(img, 0, 0, finalWidth, finalHeight);

        // 转换为 PNG 并下载
        canvas.toBlob((blob) => {
          if (blob) {
            const pngUrl = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = pngUrl;
            a.download = `mermaid-diagram-${Date.now()}.png`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(pngUrl);

            ElMessage.success('PNG 图片下载成功');
          }
          else {
            ElMessage.error('生成图片失败');
          }
        }, 'image/png', 1.0);
      };

      img.onerror = () => {
        ElMessage.error('图片加载失败');
      };

      // 设置图片源
      img.src = svgDataUrl;
    }
  }
  catch (error) {
    console.error('下载失败:', error);
    ElMessage.error('下载失败');
  }
}

// 下载为 SVG
async function downloadAsSVG() {
  if (!mermaidContainerRef.value)
    return;

  const svg = mermaidContainerRef.value.querySelector('svg');
  if (!svg)
    return;

  try {
    // 克隆 SVG
    const svgClone = svg.cloneNode(true) as SVGElement;

    // 重置变换和样式
    svgClone.style.transform = 'scale(1)';
    svgClone.style.position = 'static';
    svgClone.style.display = 'block';

    // 获取 SVG 的实际尺寸
    const bbox = svg.getBBox();
    const originalWidth = bbox.width || 800;
    const originalHeight = bbox.height || 600;

    // 设置 SVG 属性
    svgClone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
    svgClone.setAttribute('width', originalWidth.toString());
    svgClone.setAttribute('height', originalHeight.toString());
    svgClone.setAttribute('viewBox', `${bbox.x} ${bbox.y} ${originalWidth} ${originalHeight}`);

    // 确保所有文本元素可见
    const textElements = svgClone.querySelectorAll('text');
    textElements.forEach((text) => {
      text.setAttribute('fill', text.getAttribute('fill') || '#000');
      text.setAttribute('stroke', 'none');
    });

    // 转换为字符串
    const svgString = new XMLSerializer().serializeToString(svgClone);

    // 创建 Blob 并下载
    const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });
    const url = URL.createObjectURL(blob);

    const a = document.createElement('a');
    a.href = url;
    a.download = `mermaid-diagram-${Date.now()}.svg`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);

    ElMessage.success('SVG 文件下载成功');
  }
  catch (error) {
    console.error('下载失败:', error);
    ElMessage.error('下载失败');
  }
}

// 复制代码
async function copyCode() {
  try {
    await navigator.clipboard.writeText(props.content);
    ElMessage.success('代码已复制到剪贴板');
  }
  catch (error) {
    console.error('复制失败:', error);
    ElMessage.error('复制失败');
  }
}

// 监听内容变化
const { content } = toRefs(props);
watch(content, () => {
  nextTick(() => {
    renderDiagram();
  });
});

// 组件卸载时清理
onUnmounted(() => {
  // 清理事件监听器等
});
</script>

<template>
  <div :id="`mermaid-wrapper-${elementId}`" class="mermaid-wrapper">
    <!-- Mermaid 工具栏 -->
    <div class="mermaid-toolbar">
      <div class="mermaid-toolbar-left">
        <div class="mermaid-tabs">
          <div
            class="mermaid-tab"
            :class="{ active: displayState !== 'code' }"
            @click="toggleDisplay('chart')"
          >
            图表
          </div>
          <div
            class="mermaid-tab"
            :class="{ active: displayState === 'code' }"
            @click="toggleDisplay('code')"
          >
            代码
          </div>
        </div>
      </div>
      <el-button-group size="small">
        <el-button title="放大" @click="zoomIn">
          <el-icon><ZoomIn /></el-icon>
        </el-button>
        <el-button title="缩小" @click="zoomOut">
          <el-icon><ZoomOut /></el-icon>
        </el-button>
        <el-button title="全屏" class="desktop-only" @click="toggleFullscreen">
          <el-icon><FullScreen /></el-icon>
        </el-button>
        <el-dropdown trigger="click" @command="handleDownload">
          <el-button title="下载">
            <el-icon><Download /></el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="png">
                <el-icon><Download /></el-icon>
                下载为 PNG
              </el-dropdown-item>
              <el-dropdown-item command="svg">
                <el-icon><Download /></el-icon>
                下载为 SVG
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <el-button title="复制代码" @click="copyCode">
          <el-icon><DocumentCopy /></el-icon>
        </el-button>
      </el-button-group>
    </div>
    <!-- Mermaid 图表容器 -->
    <div
      :id="elementId"
      ref="mermaidContainerRef"
      class="mermaid-container"
      :data-content="content"
      style="display: flex;"
    >
      <!-- Mermaid 图表将在这里渲染 -->
    </div>

    <!-- 错误显示容器 -->
    <div ref="errorContainerRef" class="mermaid-error-container" style="display: none;">
      <div class="error-content">
        <el-icon class="error-icon">
          <WarningFilled />
        </el-icon>
        <span class="error-text">图表渲染失败</span>
      </div>
    </div>

    <!-- Mermaid 代码容器 -->
    <div ref="codeContainerRef" class="mermaid-code-container" style="display: none;">
      <pre>{{ content }}</pre>
    </div>
  </div>
</template>

<style scoped lang="scss">
.mermaid-wrapper {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  overflow: hidden;
}

.mermaid-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid #e5e7eb;
  background: #fafbfc;

  .mermaid-toolbar-left {
    display: flex;
    align-items: center;

    .mermaid-tabs {
      display: flex;
      background: #f1f5f9;
      border-radius: 6px;
      padding: 2px;

      .mermaid-tab {
        padding: 6px 16px;
        font-size: 13px;
        font-weight: 500;
        color: #64748b;
        cursor: pointer;
        border-radius: 4px;
        transition: all 0.2s ease;
        user-select: none;

        &:hover {
          color: #374151;
        }

        &.active {
          background: white;
          color: #409eff;
          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
        }
      }
    }
  }

  .el-button-group {
    .el-button {
      background: transparent;
      border: 0;
      color: #374151;
      padding: 10px 14px;
      font-size: 14px;
      min-height: 36px;
      border-radius: 6px;
      transition: all 0.2s ease;

      .el-icon {
        font-size: 16px;
        svg {
          width: 16px;
          height: 16px;
        }
      }

      &:hover {
        background: #f3f4f6;
        color: #1f2937;
        transform: translateY(-1px);
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
      }

      &:active {
        background: #e5e7eb;
        transform: translateY(0);
        box-shadow: none;
      }

      &:focus {
        outline: none;
        box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
      }
    }
  }

  .el-dropdown {
    .el-button {
      background: transparent;
      border: 0;
      color: #374151;
      padding: 10px 14px;
      font-size: 14px;
      min-height: 36px;
      border-radius: 6px;
      transition: all 0.2s ease;

      .el-icon {
        font-size: 16px;
        svg {
          width: 16px;
          height: 16px;
        }
      }

      .el-icon--right {
        margin-left: 4px;
        font-size: 14px;
        svg {
          width: 14px;
          height: 14px;
        }
      }

      &:hover {
        background: #f3f4f6;
        color: #1f2937;
        transform: translateY(-1px);
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
      }

      &:active {
        background: #e5e7eb;
        transform: translateY(0);
        box-shadow: none;
      }

      &:focus {
        outline: none;
        box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
      }
    }
  }
}

.mermaid-container {
  margin: 0;
  text-align: center;
  background: transparent;
  overflow-x: auto;
  width: 100%;
  min-height: 400px;
  overflow: auto;
  min-width: 800px;
}

.mermaid-code-container {
  margin: 0;
  background: #f6f8fa;
  border-radius: 0;
  overflow-x: hidden;
  overflow-y: auto;
  max-height: 400px;

  pre {
    margin: 0;
    padding: 16px;
    background: transparent;
    border: none;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 16px;
    line-height: 1.4;
    color: #24292e;
    white-space: pre-wrap;
    word-wrap: break-word;
    overflow-wrap: break-word;
  }

  code {
    background: transparent;
    border: none;
    padding: 0;
    font-size: inherit;
    color: inherit;
  }
}

.mermaid-error {
  border: 1px solid #ff4757;
  border-radius: 4px;
  padding: 12px;
  margin: 8px 0;

  code {
    color: #ff4757;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 12px;
    white-space: pre-wrap;
  }
}

.mermaid-error-container {
  padding: 40px 20px;
  background: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: 8px;
  margin: 16px;
  display: flex;
  justify-content: center;
  align-items: center;

  .error-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;

    .error-icon {
      font-size: 32px;
      color: #ef4444;

      svg {
        width: 32px;
        height: 32px;
      }
    }

    .error-text {
      font-size: 16px;
      font-weight: 500;
      color: #dc2626;
    }
  }
}

// 全屏模式样式
.mermaid-wrapper.fullscreen {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1009;
  background: white;
  display: flex;
  flex-direction: column;

  .mermaid-toolbar {
    background: #f8f9fa;
    border-bottom: 1px solid #e5e7eb;
    padding: 16px 20px;

    .mermaid-toolbar-left {
      .mermaid-tabs {
        display: flex;
        background: #f1f5f9;
        border-radius: 8px;
        padding: 3px;

        .mermaid-tab {
          padding: 8px 24px;
          font-size: 14px;
          font-weight: 500;
          color: #64748b;
          cursor: pointer;
          border-radius: 6px;
          transition: all 0.2s ease;
          user-select: none;

          &:hover {
            color: #374151;
          }

          &.active {
            background: white;
            color: #409eff;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
          }
        }
      }
    }

    .el-button-group {
      .el-button {
        padding: 12px 16px;
        font-size: 15px;
        min-height: 40px;
        border-radius: 8px;
        transition: all 0.2s ease;

        .el-icon {
          font-size: 18px;
          svg {
            width: 18px;
            height: 18px;
          }
        }

        &:hover {
          transform: translateY(-2px);
          box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
        }

        &:first-child {
          border-top-right-radius: 0;
          border-bottom-right-radius: 0;
        }

        &:last-child {
          border-top-left-radius: 0;
          border-bottom-left-radius: 0;
        }

        &:not(:first-child):not(:last-child) {
          border-radius: 0;
        }
      }
    }
  }

  .mermaid-container {
    flex: 1;
    padding: 24px;
    overflow: auto;
    display: flex;
    justify-content: center;
    align-items: center;

    svg {
      max-width: 100%;
      height: auto;
    }
  }

  .mermaid-code-container {
    flex: 1;
    padding: 24px;
    overflow-x: hidden;
    overflow-y: auto;
    background: #f6f8fa;
    max-height: 100vh;
    pre {
      max-height: none;
      font-size: 16px;
      white-space: pre-wrap;
      word-wrap: break-word;
      overflow-wrap: break-word;
    }
  }
}

// 手机版响应式优化
@media (width <= 768px) {
  .mermaid-container{
    min-width: 100%;
  }
  .mermaid-toolbar {
    margin: 0 8px;

    .el-button-group {
      gap: 16px;

      .el-button {
        margin: 8px 4px;
        border: 0;
      }
    }
    .desktop-only {
      display: none !important;
    }
    .mermaid-toolbar-left {
      .mermaid-tabs {
        .mermaid-tab {
          font-size: 13px;
          padding: 6px 24px;
          min-height: 36px;
          display: flex;
          align-items: center;
        }
      }
    }

    .el-button-group {
      .el-button {
        padding: 6px 20px;
        min-height: 36px;

        .el-icon {
          font-size: 18px;
          svg {
            width: 18px;
            height: 18px;
          }
        }
      }
    }

    .el-dropdown {
      .el-button {
        padding: 6px 20px;
        min-height: 36px;

        .el-icon {
          font-size: 18px;
          svg {
            width: 18px;
            height: 18px;
          }
        }

        .el-icon--right {
          margin-left: 4px;
          font-size: 14px;
          svg {
            width: 14px;
            height: 14px;
          }
        }
      }
    }
  }
}
</style>
